package com.uxsino.simo.indicator.retractor;

import java.util.HashMap;
import java.util.Map;

import com.uxsino.simo.networkentity.EntityInfo;
import com.uxsino.simo.query.QueryTemplate;
import org.mvel2.CompileException;
import org.mvel2.MVEL;
import org.mvel2.PropertyAccessException;
import org.mvel2.integration.VariableResolverFactory;
import org.mvel2.integration.impl.MapVariableResolverFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.uxsino.commons.utils.config.ConfigProp;
import com.uxsino.simo.indicator.IExprItem;
import com.uxsino.simo.query.QueryContext;

/**
 * 
 * a retractor returns result of {@link IConnection} as compound
 *
 */
public class ScriptCompoundValueRetractor extends CompoundValueRetractor implements IExprItem {
    private static Logger logger = LoggerFactory.getLogger(ScriptCompoundValueRetractor.class);

    @ConfigProp(name = "script", subElement = true)
    private String script;

    private Object compiled;

    private boolean disabled = false;

    @Override
    public Object doRetract(EntityInfo entity, QueryContext ctxt, QueryTemplate qt, Object obj) {
        if (compiled == null) {
            logger.error("can not execute script retractor due to compile failure. script:{}", script);
        }
        if (disabled) {
            logger.error("can not execute disabled script retractor. script:{}", script);
        }
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("buffer", obj);
        VariableResolverFactory variableFactory = new MapVariableResolverFactory(variables);
        variableFactory.setNextFactory(new MapVariableResolverFactory(ctxt.getVariables()));
        try {
            return MVEL.executeExpression(compiled, variableFactory);
        } catch (PropertyAccessException pae) {
            String errorExpr = new String(pae.getExpr());
            logger.error("variable not found in expression {}\n.{}", errorExpr, pae);
            return null;
        } catch (CompileException ce) {
            String errorExpr = new String(ce.getExpr());
            logger.error("compile error in expression {}\n.{}", errorExpr, ce);
            return null;

        }

    }

    @Override
    public void setFormula(String formula) {
        this.script = formula;
    }

    @Override
    public String getFormula() {
        return script;
    }

    @Override
    public Object getCompiled() {
        return compiled;
    }

    @Override
    public void setCompiled(Object compiled) {
        this.compiled = compiled;
    }

    @Override
    public void setReferredVariables(@SuppressWarnings("rawtypes") Map<String, Class> refs) {

    }

    @SuppressWarnings("rawtypes")
    @Override
    public Map<String, Class> getReferredVariables() {
        return null;
    }

    @Override
    public void disable() {
        disabled = true;
    }

    @Override
    public boolean isDisabled() {
        return disabled;
    }
}
